(function(global){  
    ujs.define('num', 'ujs', {
        /**
         * 转换信息的数量单位.
         * @method toDiskSize.
         * @param {Object} unit : K/M/G/T，默认为 M.
         * @param {Object} precision    : 结果精度，默认为 2.
         * @param {Object} isShowUnit   : 是否显示单位(KB/MB/GB/TB),默认显示.
         * @return {String}
         */
        toDiskSize : function(num, unit, precision, isShowUnit){
            var rates = {
                'K' : 1024,
                'M' : Math.pow(1024, 2),
                'G' : Math.pow(1024, 3),
                'T' : Math.pow(1024, 4)
            };
            unit = ( unit || 'M' ).toUpperCase();
            if(!rates[unit]){
                throw '不正确的信息数量单位.';
            }
            precision = precision || 2;
            isShowUnit = isShowUnit !== false;
            return ( num/rates[unit] ).toFixed( precision ) + ( isShowUnit ? unit+'B' : '' );
        }, 
        /**
         * 重写 toFixed 方法.
         * @method toFixed
         * @param num {Number} 指定保留几位小数.
         * @param isRemoveEndZero {Boolean} 是否去掉末尾的0.
         * @return {String} 
         */
        toFixed : (function(){
            var originalToFixed = Number.prototype.toFixed;
            return function(number, num, isRemoveEndZero){  
                var fixedValue = originalToFixed.call( Number(number), num || 2 );
                if(isRemoveEndZero){
                    fixedValue = fixedValue / 1 + '';
                }       
                return fixedValue;
            };
        })(),
        /**
         * 取整.
         * @method toInt
         * @return {Number}
         */
        toInt : function(num, base){
            return parseInt(num, base || 10);
        },
        /**
         * 获取浮点数.
         */
        toFloat : function(num){
            return parseFloat(num);
        },
        /**
         * Return true if number is a float
         * @method isFloat
         * @return {Boolean}
         */
        isFloat : function(num) {
            return /\./.test(num.toString());
        },
        /**
         * Return true if number is an integer
         * @method isInteger
         * @return {Boolean}
         */
        isInteger : function(num) {
            return Math.floor(num) == num;
        },
        /**
         * 判断数字是否在指定的区间内.
         * [4000-5000], (4000-5000), (4000-5000], [4000-5000)
         */
        isInRegion : function(num, numberRegionStr){
            var flag = false;
            if(numberRegionStr && numberRegionStr.isNumberRegion()){
                var numberParts = numberRegionStr.split('-'),
                    numberPartOne = numberParts[0],
                    numberPartTwo = numberParts[1];                
                var numberPartOneRegionType = numberPartOne.substr(0,1);
                var numberPartOneValue = parseInt(numberPartOne.substr(1));
                if((numberPartOneRegionType == '[' && num >= numberPartOneValue) || (numberPartOneRegionType == '(' && num > numberPartOneValue)) {            
                    var numberPartTwoRegionType = numberPartTwo.substr(numberPartTwo.length - 1,1);
                    var numberPartTwoValue = parseInt(numberPartTwo.substr(0, numberPartTwo.length - 1));
                    if((numberPartTwoRegionType == ']' && num <= numberPartTwoValue) || (numberPartTwoRegionType == ')' && num < numberPartTwoValue)) {
                        flag = true;
                    }
                } 
            }
            return flag;
        },
        /**
         * 将指定的函数执行n次.
         */
        times : function(num, fn, ctx){
            for(var i = 0; i < num; i++){ 
                fn.call(ctx, i, num);
            }
        },                
        /**
         * 将 10 转换成 '+10',
         * 将 -10 转换成 '-10'.
         * @method toSignedNumberString
         * @param zeroPrefix {String} : 0之前的字符，一般用 +号，默认为空字符串。
         * @return {String}
         */
        toSignedNumberString : function(num, zeroPrefix){    
            if(num > 0){
                return '+' + String(num);        
            } else if(num == 0){
                return (zeroPrefix || '') + String(num);
            } else {
                return String(num);
            }
        },
        /**
         * 左填充。
         * @method paddingLeft
         * @param paddingStr {String|Function} 填充值，默认为0.
         * @return {String}
         */
        paddingLeft : function(num, paddingStr /* or paddingFun */){
            if(!paddingStr){
                paddingStr = '0';
            }
            if(!ujs.Type.isFunction(paddingStr)){
                var paddingFun = function(num){
                    return num.inRegion(0, 9, true) ? (paddingStr + num) : num + '';
                };
            } else {
                var paddingFun = paddingStr;
            }
            return paddingFun(num);
        },
        /**
         * 约束数值在指定的范围[min, max]。
         * @method constraintRegion
         * @param min {Number} 最小值.
         * @param max {Number} 最大值.
         * @return {Number}.
         */
        constraintRegion : function(num, min, max){
            if(num < min){
                return min;
            } 
            if(num > max){
                return max;
            }   
            return num;
        },    
        /**
         * 判断数值是否在指定的范围内[min, max]。
         * @method inRegion
         * @param min {Number} 最小值.
         * @param max {Number} 最大值.
         * @param isClosed {Boolean} 是否是闭区间，默认false.
         * @return {Boolean}.
         */
        inRegion : function(num, min, max, isClosed){    
            return (isClosed === true && num >= min && num <= max) || (!isClosed && num > min && num < max );
        },
        /**
         * 获取当前数值的相反数.
         * @method negetive
         * @return {Number} 
         */
        negetive : function(num){
            return -num;
        },
        /**
         * Return the hexidecimal string representation of an integer
         * @method toHex
         * @return {String}
         */
        toHex : function(num) {
            return num.toString(16);    
        },
        /**
         * 判断指定的数值是否是有限的(参数可能是一个表达式).
         * @static
         * @method isFinite
         * @param {Number} 
         * @return {Boolean}
         */
        isFinite : function(number){
            if(typeof number === 'number' || number instanceof Number){
                return number != Infinity;
            } else {
                return false;
            }
        },        
        /**
         * 将数字转换成金额大写格式.
         * @static
         * @method toAmountWords
         * @param {Number}
         * @return {String}
         */
        toAmountWords : function(amount){
            var dw2 = ["", "万", "亿"]; //大单位
            var dw1 = ["拾", "佰", "仟"]; //小单位
            var dw = ["零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"]; //整数部分用
        
            var amountSource = String(amount).split('.');
            
            //转换整数部分
            var k1 = 0; //计小单位
            var k2 = 0; //计大单位
            var sum = 0;
            var str = "";
            var n = 0;
        
            for (var i = 1, len = amountSource[0].length; i <= len; i++) {
                n = amountSource[0].charAt(len - i); //取得个位数上的数字
                var bn = 0;
                if (len - i - 1 >= 0) {
                    bn = amountSource[0].charAt(len - i - 1); //取得某个位数前一位上的数字
                }
                sum = sum + Number(n);
                if (sum != 0) {
                    str = dw[Number(n)].concat(str); //取得该数字对应的大写数字，并插入到str字符串的前面
                    if (n == '0') sum = 0;
                }
                if (len - i - 1 >= 0) { //在数字范围内
                    if (k1 != 3) { //加小单位
                        if (bn != 0) {
                            str = dw1[k1].concat(str);
                        }
                        k1++;
                    } else { //不加小单位，加大单位
                        k1 = 0;                
                        if (str.charAt(0) == "万" || str.charAt(0) == "亿") //若大单位前没有数字则舍去大单位
                            str = str.substr(1, str.length - 1);
                        str = dw2[k2].concat(str);
                        sum = 0;
                    }
                }
                if( k1 == 3 ) { //小单位到千则大单位进一        
                    k2++;
                }
            }
            str += "元";
            
            //转换小数部分    
            if (amountSource[1]) {
                n = amountSource[1].charAt(0);
                if (n != 0) {
                    str += dw[Number(n)] + "角";
                }
                n = amountSource[1].charAt(1);
                if (n != 0) {
                    str += dw[Number(n)] + "分";
                }
            } else {
                str += '整';    
            }
            
          return str;
        },
        /**
         * 获取下一个模数.
         * @method nextModule
         * @param {Number} module 模单位大小.
         * @return {Number}
         */
        nextModule : function(num, module){
            if(!module){
                return num;
            }
            module = Math.abs(module);    
            var remainder = num % module;
            if(remainder === 0){
                return num + module;
            }    
            var modulePointer = parseInt( num / module );    
            if(modulePointer > 0 || ( modulePointer === 0 && num >= 0 )){
                modulePointer++;
            }    
            return modulePointer * module;
        },
        /**
         * 获取上一个模数.
         * @method prevModule
         * @param {Number} module 模单位大小.
         * @return {Number}
         */
        prevModule : function(num, module){
            if(!module){
                return num;
            }
            module = Math.abs(module);
            
            var remainder = num % module;
            if(remainder === 0){
                return num - module;
            }
            
            var modulePointer = parseInt( num / module );    
            if(modulePointer < 0 || ( modulePointer === 0 && num <= 0 )){
                modulePointer--;
            }    
            return modulePointer * module;
        }
    });        
    
    ujs.alias(ujs.num, ujs.num.times, 'each');    
    ujs.alias(ujs.num, ujs.num.toFixed, 'round');    
    ujs.alias(ujs.num, ujs.num.constraintRegion, 'limit');
    
})(window);